// 引入sme-router
import SMERouter from 'sme-router'

// 引入一个测试代码(只希望这个文件能够执行以下,被webpack编译)
// import './js/test'

// import './xxx/yyy/zzz/test.js' 配置路径别名之前
// import 'z/test.js' // 配置路径别名之后
// 引入模板
import index from 't/index'
import login from 't/login'
import admin from 't/adminList'
import adv from 't/advList'

// 引入发送请求的函数
// 注意: 如果要引入某个文件夹下面的index.js,则index.js可以忽略不写.引入路径写到这个文件夹就可以了
import {
  getAdmins,
  reqLogin,
  reqVerifyToken,
  reqLogout,
  reqAddAdv,
  reqGetAdvs,
  reqDelAdv,
} from './api'

// 引入moment.js. moment的作用: 帮我们格式化日期
import moment from 'moment'
window.moment = moment // 由于模板中可以直接使用全局的对象或方法,所以将moment添加到全局,然后在模板中直接进行格式化

// 创建SMERouter实例
// root是index.html中根标签的id名
// 注意: 前端路由都有两种模式: 1. history模式(路径和视图的一一对应关系,未来修改的也是路径) 2. hash模式(浏览器地址栏的hash值和视图的一一对应关系,未来修改的是hash值)
// 完整的url地址: 协议://域名:端口号/路径?查询字符串#hash值
// sme-router默认模式是hash模式
// html5这个参数,就是让sme-router由hash模式,改为history模式
const router = new SMERouter('root', 'html5')
// 由于模板中要直接使用router,所以直接将router添加到window
// 模板中中直接调用全局的变量
window.router = router

// 配置前端路由规则
// router.route('/路径',回调函数)
router.route('/login', (req, res) => {
  // res.render运行之后,登录的结构就渲染在页面上了
  res.render(login())
  // 一定要在登录结构渲染到页面上之后获取登录按钮
  // 1. 获取登录按钮
  const loginBtn = document.getElementById('login-btn')
  // 2. 给登录按钮绑定点击事件
  loginBtn.onclick = async function (e) {
    // 阻止form的默认行为
    e.preventDefault()

    //3.收集用户输入的信息
    const username = document.getElementById('username').value.trim()
    const password = document.getElementById('password').value.trim()

    // 4. 判断用户名和密码是否有值,如果都有值,则发送请求,否则不发送请求
    if (username && password) {
      // 可以发送请求了
      const result = await reqLogin(username, password)
      // 判断code为2表示登录成功
      if (result.code === 2) {
        // 5. 存储token
        localStorage.setItem('token', result.data)
        localStorage.setItem('username', username)
        // 6. 提示用户
        toastr.success(result.message)
        // 7. 跳转到首页
        router.go(`/index?username=${username}`)
      } else {
        // 提示用户
        toastr.error(result.message)
      }
    } else {
      // 不能发请求
      toastr.error('请输入用户名和密码再进行登录')
    }
  }
})
router.route('/index', async (req, res, next) => {
  //   console.log(res.subRoute()) //返回一个用于渲染二级路由结构的div标签
  // 注意: 由于首页中有子级路由(嵌套路由),所以应该使用next

  //   console.log(req.url) // 获取当前地址栏的路径

  // 注意: 由于在/index中写了return也不能阻止/index/admin或/index/adv的回调执行,所以
  // 首页,管理员页,广告页中都要发送请求校验token
  // 由于广告页和管理页已经校验过了,所以首页校验的请求加一个判断.只在当req.url为/index的时候才去校验
  if (req.url === '/index') {
    const result = await reqVerifyToken()
    if (result.code !== 2) {
      toastr.error(result.message)
      res.redirect('/login')
      return
    }
  }

  next(
    index({
      // 将二级路由结构要渲染的div标签传入到模板中,在指定位置渲染出来
      subRoute: res.subRoute(),
      url: req.url,
      username: req.query?.username || localStorage.getItem('username'),
    })
  )

  // 获取退出登录按钮,并绑定点击事件
  const logout = document.getElementById('logout')
  logout.onclick = async function () {
    // 发送请求,请求退出
    const result = await reqLogout()
    if (result.code === 2) {
      // 服务器退出成功了,然后前端要删除本地缓存的token
      localStorage.setItem('token', '')
      // 提示用户退出成功,
      toastr.success(result.message)
      // 跳转到登录页
      router.go('/login')
    } else {
      // 提示用户退出失败
      toastr.error(result.message)
    }
  }
})
// 配置首页的二级路由管理员和广告页面
// 注意: 二级路由的路径必须以一级路由的路径开头
router.route('/index/admin', async (req, res) => {
  // 验证token
  const result1 = await reqVerifyToken()
  if (result1.code !== 2) {
    toastr.error(result1.message)
    res.redirect('/login')
    return
  }
  //发送请求获取管理员数据
  const result = await getAdmins()
  console.log(result)
  if (result.code === 2) {
    // 提示用户
    toastr.success(result.message)
    // 拿到数据了
    res.render(admin(result.data))
  } else {
    // 请求响应成功了,但是没有拿到数据
    toastr.error(result.message)
  }
})

router.route('/index/adv', async (req, res) => {
  // 验证token
  const result1 = await reqVerifyToken()
  if (result1.code !== 2) {
    toastr.error(result1.message)
    res.redirect('/login')
    return
  }

  // 渲染广告之前,先获取广告页的数据
  const result = await reqGetAdvs()
  if (result.code === 2) {
    // 拿到数据了
    // 渲染广告页
    res.render(adv(result.data))
  } else {
    toastr.error(result.message)
  }

  // 点击添加广告的保存按钮,添加广告信息
  async function saveHandle() {
    // 获取表单form的dom对象
    const form = document.getElementById('form')
    // 创建formdata实例
    const formdata = new FormData(form)

    // 表单校验, 检查四条数据是否都写了,如果都写了才发送请求,如果有一个没写就不发请求,并提示用户
    const advTitle = formdata.get('advTitle')
    const advCate = formdata.get('advCate')
    const advLink = formdata.get('advLink')
    const file = formdata.get('file')
    // console.log(file)
    // 注意: 如果没有选择文件,拿到的file也是一个对象.所以要判断是否选择了文件,要看file.size是否有值
    if (advTitle && advCate && advLink && file.size) {
      //发送请求
      const result = await reqAddAdv(formdata)
      if (result.code === 2) {
        // 提示用户
        toastr.success(result.message)

        // 如果添加成功了,则result.data就一定是最新的数据
        // res.render(adv(result.data))

        res.redirect('/index/adv')

        // // 由于上面重新渲染了广告页面的所有结构,所以原来绑定了事件的dom已经被覆盖了,重新创建的新dom没有绑定任何事件.所以重新渲染之后,需要重新绑定事件
        // const saveBtn = document.getElementById('saveAdv')
        // saveBtn.onclick = saveHandle

        // // 获取选择文件的表单项
        // const file = document.querySelector('input[name=file]')
        // // 给上传文件的表单项绑定change事件
        // file.onchange = previewHandle
      } else {
        toastr.error(result.message)
      }
    } else {
      toastr.error('请正确填写表单')
    }
  }
  const saveBtn = document.getElementById('saveAdv')
  saveBtn.onclick = saveHandle

  // 预览图片
  function previewHandle(e) {
    // 获取预览图片的img标签的dom对象
    const preImg = document.getElementById('preImg')
    // 利用readFile生成选择的图片的base64,然后添加给preImg的src
    const reader = new FileReader()
    // 如果没有选中图片,则把一个没有内容的file对象进行base64转换会报错,所以使用trycatch.
    // 如果没有选中图片,则会执行catch中的代码
    try {
      // 要将选中的图片,转成base64
      reader.readAsDataURL(e.target.files[0])
      // 获取把图片转成base64的结果(当reader把图片转成base64之后.onload事件会触发)
      reader.onload = function (e) {
        // console.log(e.target.result) // 通过这个属性获取转换之后的base64
        // 把转换好的base64赋值给preImg的src
        preImg.src = e.target.result
      }
    } catch (error) {
      preImg.src = ''
    }
  }
  // 获取选择文件的表单项
  const file = document.querySelector('input[name=file]')
  // 给上传文件的表单项绑定change事件
  file.onchange = previewHandle

  // 删除广告数据
  async function delAdvHandle(e) {
    // 判断事件目标是否是删除按钮,不是删除按钮,则什么都不做.是删除按钮才发送请求删除数据
    if (e.target.className.includes('delBtn')) {
      // 能进来这里说是删除按钮
      // 获取要删除的这条数据的id
      const id = e.target.id
      // 发送请求,删除数据
      const result = await reqDelAdv(id)
      if (result.code === 2) {
        toastr.success(result.message)
        res.redirect('/index/adv')
      } else {
        toastr.error(result.message)
      }
    }
  }
  // 由于有很多删除按钮,所以为了方便,使用事件委托的形式,把删除事件绑定在tbody标签上
  const tbody = document.getElementById('adv-tbody')
  tbody.onclick = delAdvHandle

  // 修改按钮的点击事件
  tbody.addEventListener('click', function (e) {
    // 如果点击的是修改按钮,才执行后面的代码
    if (e.target.className.includes('updateBtn')) {
      // 把模态框的标题和保存按钮的文本,改成`修改`
      // 模态框的标题标签
      const modalTitle = document.querySelector('.modal-title')
      // 保存按钮上面已经获取过了
      // 修改模态框标题和按钮的文本
      modalTitle.innerText = '修改广告'
      saveBtn.innerText = '修改'
    }
  })

  // 获取添加广告按钮,并绑定点击事件
  const advAddBtn = document.getElementById('advAddBtn')
  advAddBtn.onclick = function () {
    // 把模态框的标题和保存按钮的文本,改成`修改`
    // 模态框的标题标签
    const modalTitle = document.querySelector('.modal-title')
    // 保存按钮上面已经获取过了
    // 修改模态框标题和按钮的文本
    modalTitle.innerText = '添加广告'
    saveBtn.innerText = '保存'
    // 清空表单
    const form = document.getElementById('form')
    form.reset() // 重置表单(恢复到表单的默认值状态,但是刚好我们表单的默认值状态都是空的.所以重置表单,相当于就是清空表单)
  }
})

router.route('*', (req, res) => {
  //   res.render('<h1>您查找的页面不存在</h1>')
  res.redirect('/login')
})
